//!
/**
 ***********************************************************************************************************
 * <RBRenderPass Implementation>
 ***********************************************************************************************************
 * @file RBRenderPass.cpp
 ***********************************************************************************************************/

/***********************************************************************************************************
 * Precompiled Header
 ***********************************************************************************************************/
#include "RBMainPCH.h"

/***********************************************************************************************************
 * Includes
 ***********************************************************************************************************/
#include "RBRenderPass.h"

#include "RBBVolume.h"
#include "RBEntity.h"
#include "RBRenderer.h"
#include "RBGeometry.h"
#include "RBVisibilityManager.h"
#include "RBDefaultGeometrySorter.h"
#include "RBVisibilityComponent.h"

#include "RBRenderProcess/RBRenderTargetView.h"
#include "RBRenderProcess/RBDepthStencilView.h"

/***********************************************************************************************************
 * Defines
 ***********************************************************************************************************/

/***********************************************************************************************************
 * Classes implementation
 ***********************************************************************************************************/

namespace rb_render_pass
{

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void open_render_target_group(RBRenderer* pRenderer, RBRenderTargetGroup* pRenderTargetGroup, uint32 clearFlags, const RBColorA& clearColor, float32 clearDepth,
                           float32 x, float32 y, float32 width, float32 height, float32 zMin, float32 zMax)
{
    RBTexture* pRT = (pRenderTargetGroup->GetBufferCount() > 0) ? pRenderTargetGroup->GetRenderTargetView()->GetBuffer() : pRenderTargetGroup->GetDepthStencilView()->GetBuffer();
    pRenderer->clear_state();
    pRenderer->RSSetViewport(RBViewPort(x * pRT->GetWidth(), y * pRT->GetHeight(), width * pRT->GetWidth(), height * pRT->GetHeight(), zMin, zMax));
    pRenderer->ClearRenderTargets(pRenderTargetGroup, clearColor, clearDepth, clearFlags);
    pRenderer->OMSetRenderTargets(pRenderTargetGroup->GetBufferCount(), pRenderTargetGroup->GetRenderTargetViews(), pRenderTargetGroup->GetDepthStencilView());
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void render_geometries(RBRenderer* pRenderer, const RBGeometryArray& aVisibleGeometries, RBCamera* camera)
{
    PROFILE_FUNC();
    pRenderer->UpdateCamera(camera);
    for (uint32 ui=0; ui<aVisibleGeometries.size(); ++ui)
    {
        if (aVisibleGeometries[ui]->IsVisible)
        {
            pRenderer->Render(aVisibleGeometries[ui]);
        }
    }
}

/***********************************************************************************************************
 *
 ***********************************************************************************************************/
void collect_geometries(RBGeometryArray* output, RBCamera* camera, RBVisibilityManager* scene)
{
    RBBVolumeArray input;
    scene->start_visibility(camera, 0);
	output->reserve(input.size());
	scene->sync_visibility_results(&input, 1<<0);
    for (uint32 uiEntity=0; uiEntity < input.size(); ++uiEntity)
    {
        RBBVolume& visibleNode = RBBVolume::Get(input[uiEntity]);
        uint16 objectType = visibleNode.GetObjectType();
        if (objectType != RBGeometry::GetClassIdx())
        {
            continue;
        }

        RBGeometryHandle pGeometryComponent =  visibleNode.GetObject<RBGeometry>();

        output->push_back(pGeometryComponent);
    }

    RBDefaultGeometrySorter sorter(camera);
    std::sort(output->begin(), output->end(), sorter);
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void PushTechniques( const RBGeometryArray& vGeometries, std::vector<RBEffect*>& vEffects, RBEffect* pEffect )
{
    vEffects.resize(vGeometries.size());
    for (uint32 ui=0; ui<vGeometries.size(); ++ui)
    {
        vEffects[ui] = vGeometries[ui]->GetMaterial()->GetEffect();
    }

    for (uint32 ui=0; ui<vGeometries.size(); ++ui)
    {
        vGeometries[ui]->GetMaterial()->SetEffect(pEffect);
    }
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void PopTechniques( const RBGeometryArray& vGeometries, const std::vector<RBEffect*>& vEffects )
{
    for (uint32 ui=0; ui<vGeometries.size(); ++ui)
    {
        vGeometries[ui]->GetMaterial()->SetEffect(vEffects[ui]);
    }
}

}